package weixin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import com.alibaba.fastjson.JSON;

/**
 * 目录 1 第一步：用户同意授权，获取code 2 第二步：通过code换取网页授权access_token 3
 * 第三步：刷新access_token（如果需要） 4 第四步：拉取用户信息(需scope为 snsapi_userinfo) 5
 * 附：检验授权凭证（access_token）是否有效
 * 
 * @author zcc
 * 
 */
public class SnsUserInfoDemo {

	/**
	 * 公众号的唯一标识
	 */
	private static String appid = "wx43fdd59a150361cc";

	/**
	 * 公众号的appsecret
	 */
	private static String secret = "6baebca1dbfdcbd08a771248c6adb5f9";

	/**
	 * 授权后重定向的回调链接地址，请使用urlencode对链接进行处理
	 */
	private static String redirect_uri = "http://blb.zjhc.net.cn";

	/**
	 * 返回类型，请填写code
	 */
	private static String response_type = "code";

	/**
	 * 应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo
	 * （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）
	 */
	private static String scope = "snsapi_userinfo";

	/**
	 * 重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节
	 */
	private static String state = "";

	/**
	 * 分享url示例：https://open.weixin.qq.com/connect/oauth2/authorize?
	 * appid=wxf0e81c3bee622d60
	 * &redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php
	 * &response_type=code &scope=snsapi_userinfo &state=STATE#wechat_redirect
	 * 如果用户同意授权，页面将跳转至
	 * redirect_uri/?code=CODE&state=STATE。若用户禁止授权，则重定向后不会带上code参数
	 * ，仅会带上state参数redirect_uri?state=STATE
	 * 
	 * code说明 ：
	 * code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
	 */
	
	/**
	 * 通过code换取网页授权access_token
	 * code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
	 * appid 公众号的唯一标识 
	 * secret 公众号的appsecret 
	 * code 填写第一步获取的code
	 * 参数 grant_type填写为authorization_code
	 * 
	 * @return
	 */
	public static WebAccessToken getWebAccessToken(String code) {
			String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
							+ appid + "&secret=" + secret + "&code=" + code
							+ "&grant_type=authorization_code";
			/**
			 * 正确时返回的JSON数据包如下：
			 * 
			 * { "access_token":"ACCESS_TOKEN", "expires_in":7200,
			 * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID",
			 * "scope":"SCOPE" } 
			 * access_token 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同 
			 * expires_in access_token接口调用凭证超时时间，单位（秒）
			 *  refresh_token 用户刷新access_token
			 * openid 用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID 
			 * scope 用户授权的作用域，使用逗号（,）分隔
			 * 
			 * 错误时微信会返回JSON数据包如下（示例为Code无效错误）:
			 * 
			 * {"errcode":40029,"errmsg":"invalid code"}
			 */
			String json = httpReauest(url);
			System.out.println(json.toString());
			json = json.replace("null", "");
			if(json == null||json.contains("errcode"))
				return null;
			else{
				WebAccessToken webAccessToken = JSON.parseObject(json, WebAccessToken.class);
				return webAccessToken;
			}
	}
	
	/**
	 * 刷新access_token（如果需要）
	 * 
	 * 由于access_token拥有较短的有效期，当access_token超时后，可以使用refresh_token进行刷新，
	 * refresh_token拥有较长的有效期（7天、30天、60天、90天），当refresh_token失效的后，需要用户重新授权。
	 */
	public static WebAccessToken refreshAccessToken(String refresh_token){
		/**
		 * appid 是 公众号的唯一标识
		 *  grant_type 是 填写为refresh_token 
		 *  refresh_token 是填写通过access_token获取到的refresh_token参数
		 */
		String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+appid+"&grant_type="+refresh_token+"&refresh_token=REFRESH_TOKEN";
		String json = httpReauest(url);
		System.out.println(json);
		
		/**
		 * 正确时返回的JSON数据包如下：
		 * 
		 * { "access_token":"ACCESS_TOKEN", "expires_in":7200,
		 * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
		 * 
		 * access_token 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
		 * expires_in access_token 接口调用凭证超时时间，单位（秒）
		 *  refresh_token 用户刷新access_token 
		 *  openid 用户唯一标识
		 *  scope 用户授权的作用域，使用逗号（,）分隔
		 */
		if(json == null)
			return null;
		else{
			WebAccessToken webAccessToken = JSON.parseObject(json, WebAccessToken.class);
			return webAccessToken;
		}
	}
	
	/**
	 * 检验授权凭证（access_token）是否有效
	 * @param access_token
	 * @param openid
	 */
	public static WebAccessToken valdateAccessToken(String access_token,String openid){
		String url = "https://api.weixin.qq.com/sns/auth?access_token="+access_token+"&openid="+openid;
		/**
		 * 正确的Json返回结果：
		 * 
		 * { "errcode":0,"errmsg":"ok"} 错误时的Json返回示例：
		 * 
		 * { "errcode":40003,"errmsg":"invalid openid"}
		 */
		
		String json = httpReauest(url);
		if(json == null)
			return null;
		else{
			WebAccessToken webAccessToken = JSON.parseObject(json, WebAccessToken.class);
			return webAccessToken;
		}
	}
	
	/**
	 * 拉取用户信息(需scope为 snsapi_userinfo)
	 */
	public static WeixinUser getUserInfo(String access_token,String openId){
		/**
		 * access_token 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
		 *  openid用户的唯一标识 
		 *  lang 返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语
		 */
		String url = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+openId+"&lang=zh_CN";
		
		/**
		 * 正确时返回的JSON数据包如下：
		 * 
		 * { "openid":" OPENID", " nickname": NICKNAME, "sex":"1",
		 * "province":"PROVINCE" "city":"CITY", "country":"COUNTRY",
		 * "headimgurl":
		 * "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46"
		 * , "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ] "unionid":
		 * "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
		 * 
		 * openid 用户的唯一标识 nickname 用户昵称 sex 用户的性别，值为1时是男性，值为2时是女性，值为0时是未知
		 * province 用户个人资料填写的省份 city 普通用户个人资料填写的城市 country 国家，如中国为CN headimgurl
		 * 用户头像
		 * ，最后一个数值代表正方形头像大小（有0、46、64、96、132数值可选，0代表640*640正方形头像），用户没有头像时该项为空。
		 * 若用户更换头像，原有头像URL将失效。 privilege 用户特权信息，json 数组，如微信沃卡用户为（chinaunicom）
		 * unionid 只有在用户将公众号绑定到微信开放平台帐号后，才会出现该字段。详见：获取用户个人信息（UnionID机制）
		 * 
		 * 错误时微信会返回JSON数据包如下（示例为openid无效）:
		 * 
		 * {"errcode":40003,"errmsg":" invalid openid "}
		 */
		
		String json = httpReauest(url);
		if(json == null)
			return null;
		else{
			WeixinUser weixinUser = JSON.parseObject(json, WeixinUser.class);
			return weixinUser;
		}
	}
	
	private static String httpReauest(String rqRrl){
		HttpURLConnection con = null;
		try {
			URL url = new URL(rqRrl);
			con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("POST");
			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 
			
			String line,returnjson = null;
			while ((line = in.readLine()) != null) {
				returnjson +=line;
			}
			return returnjson;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	
	public static void main(String[] args){
		
	}
}
